
import java.util.ArrayList;
import java.util.Arrays;
import tester.Tester;

// examples class, runs tests
public class ExamplesMazeGame {

    // MazeGame
    MazeGame mg = new MazeGame(10, 10);

    // Node's
    Node node1 = new Node();
    Node node2 = new Node();
    Node node3 = new Node();
    Node node4 = new Node();

    // Edge's
    Edge edge1 = new Edge(node1, node2, 4, "horizontal");
    Edge edge2 = new Edge(node1, node3, 1, "vertical");
    Edge edge3 = new Edge(node2, node4, 2, "vertical");

    // Branch's
    Branch b1 = new Branch(node1);
    Branch b2 = new Branch(node2);
    Branch b3 = new Branch(node3);
    Branch b4 = new Branch(node4);

    // Point's
    Point p1 = new Point(0, 0);
    Point p2 = new Point(0, 1);
    Point p3 = new Point(0, 0);

    // ArrayList<Edge>
    ArrayList<Edge> edges = new ArrayList<Edge>(
            Arrays.asList(edge1, edge2, edge3));

    // empty constructor
    public ExamplesMazeGame() {
        // empty
    }

    // to reset data
    void reset() {
        mg = new MazeGame(10, 10);
        mg.init();

        node1 = new Node();
        node2 = new Node();
        node3 = new Node();
        node4 = new Node();

        edge1 = new Edge(node1, node2, 4, "horizontal");
        edge2 = new Edge(node1, node3, 1, "vertical");
        edge3 = new Edge(node2, node4, 2, "vertical");

        b1 = new Branch(node1);
        b2 = new Branch(node2);
        b3 = new Branch(node3);
        b4 = new Branch(node4);

        p1 = new Point(0, 0);
        p2 = new Point(0, 1);
        p3 = new Point(0, 0);

        edges = new ArrayList<Edge>(
                Arrays.asList(edge1, edge2, edge3));
    }

    // to test edgesSort(ArrayList<Edges>)
    void testEdgesSort(Tester t) {
        reset();     
        t.checkExpect(mg.edgesSort(edges), 
                new ArrayList<Edge>(Arrays.asList(edge2, edge3, edge1)));
        t.checkExpect(mg.edgesSort(new ArrayList<Edge>()),
                new ArrayList<Edge>());
    }

    // to test canReach(Node, Node, String)
    void testCanReach(Tester t) {
        reset();
        node1.right = node2;
        node2.left = node1;
        t.checkExpect(mg.canReach(node1, node1, ""), true);
        t.checkExpect(mg.canReach(node1, node2, ""), true);
        t.checkExpect(mg.canReach(node1, node3, ""), false);
    }

    // to test init()
    void testInit(Tester t) {
        reset();
        mg.init();
        t.checkExpect(mg.canReach(mg.graph.get(new Point(0, 0)),
                mg.graph.get(new Point(9, 9)), ""), true);
        t.checkExpect(mg.status, "start");
        t.checkExpect(mg.graph.get(new Point(0, 0)).status, "checking");
    }

    // to test kruskal(ArrayList<Edge>)
    void testKruskal(Tester t) {
        reset();
        mg.kruskal(edges);
        t.checkExpect(edges.isEmpty(), true);
        t.checkExpect(mg.graph.isEmpty(), false);
    }

    // to test onKeyEvent(String)
    void testOnKeyEvent(Tester t) {
        reset();
        mg.onKeyEvent("m");
        t.checkExpect(mg.status, "manual");
        mg.onKeyEvent("b");
        t.checkExpect(mg.status, "breadth");
        mg.onKeyEvent("d");
        t.checkExpect(mg.status, "depth");
    }

    // to test onManualKeyEvent(String)
    void testOnManualKeyEvent(Tester t) {
        reset();
        t.checkExpect(mg.equals(mg.onManualKeyEvent("up")), true);
    }

    // to test makeImage()
    void testMakeImage(Tester t) {
        reset();
        t.checkExpect(mg.makeImage(), mg.makeImage());
    }

    // to test onTick()
    void testOnTick(Tester t) {
        reset();
        mg.onKeyEvent("b");
        t.checkExpect(mg.graph.get(new Point(0, 0)).status, "checking");
        mg.onTick();
        t.checkExpect(mg.graph.get(new Point(0, 0)).status, "checked");
    }

    // to test breadthTick()
    void testBreadthTick(Tester t) {
        reset();
        mg.init();
        t.checkExpect(mg.graph.get(new Point(0, 0)).status, "checking");
        mg.breadthTick(mg.tree);
        t.checkExpect(mg.graph.get(new Point(0, 0)).status, "checked");
    }

    // to test initTree(Branch, Branch)
    void testInitTree(Tester t) {
        reset();
        node1.right = node2;
        b2.parent = b1;
        node1.initTree(b1, b1);
        t.checkExpect(b1.children.get(0), b2);
        t.checkExpect(b1.children.get(0).parent, b1);
    }

    // to test equals(Object)
    void testEquals(Tester t) {
        reset();
        t.checkExpect(p1.equals(p3), true);
        t.checkExpect(p1.equals("hey"), false);
        t.checkExpect(p1.equals(p2), false);
    }

    // to test hashCode()
    void testHashCode(Tester t) {
        reset();
        t.checkExpect(p1.hashCode(), 0);
        t.checkExpect(p1.hashCode(), p2.hashCode());
        t.checkExpect(p1.hashCode(), p3.hashCode());
    }

    // to test depthTick()
    void testDepthTick(Tester t) {
        reset();
        mg.init();
        t.checkExpect(mg.graph.get(new Point(0, 0)).status, "checking");
        mg.tree.depthTick();
        t.checkExpect(mg.graph.get(new Point(0, 0)).status, "checked");
    }

}
